package scalab.core.component

//import scalab.core.Dependency
import scalab.utils.{Digest, MD5}
import scalab.core.dependencies.Dependency

trait Selector extends Filter{

	val in = mandatoryIn

	val staticDependencies: Iterable[Dependency]
	
	def execute: Boolean = {
		transmit(
			if(in.hasUniverse)
				staticDependencies
			else
				in.sources filter {d => select(d)}
		)
		//info("products: " + productDependencies)
		returnValue
	}

	def select(d: Dependency): Boolean

	//warning, not complement when connected to universe
	def complement: Selector = Selector("!"+name,{d: Dependency => !select(d)},staticDependencies)

	//todo: def inverse

	//is the iterable of the set always ordered the same way
	def instanceId: String = {
		val md = MD5.getMessageDigest
		staticDependencies foreach {d =>
			Digest.update(md, d.isHard + d.canonicalPath)
		}
		Digest.getHash(md)
	}
	//staticDependencies should NOT influence instanceID because it does not (always) influence
	//the behavior of the selector but only the dependencies it yields.
	//a selector (and more generally any component) connected to the universe should never be cached...

	def returnValue: Boolean = true
}

object Selector{

	import java.io.File

	def apply(componentName: String, selector: (Dependency => Boolean), staticDeps: Iterable[Dependency]): Selector = new Selector{
		override def select(d: Dependency): Boolean = selector(d)
		override val name: String = componentName
		override val staticDependencies = staticDeps.toList
	}

	def apply(selector: (Dependency => Boolean), staticDeps: Iterable[Dependency]): Selector = apply("Selector", selector, staticDeps)
	def apply(componentName: String, selector: (Dependency => Boolean)): Selector = apply(componentName, selector, Nil)
	def apply(selector: (Dependency => Boolean)): Selector = apply(selector, Nil)
}
